package com.hitqz.robot.biz.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.xiaoymin.knife4j.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.hitqz.robot.api.business.enums.MediaEnum;
import com.hitqz.robot.api.common.entity.PatrolCheckType;
import com.hitqz.robot.api.common.entity.Robot;
import com.hitqz.robot.api.common.entity.RobotEquipment;
import com.hitqz.robot.biz.core.FileProperties;
import com.hitqz.robot.biz.flow.util.LiteFlowUtil;
import com.hitqz.robot.biz.mapper.PatrolCheckTypeMapper;
import com.hitqz.robot.biz.service.PatrolCheckTypeService;
import com.hitqz.robot.biz.service.RobotEquipmentService;
import com.hitqz.robot.biz.service.RobotService;
import com.hitqz.robot.camera.EquipmentFactory;
import com.hitqz.robot.camera.IEquipmentService;
import com.hitqz.robot.camera.configure.EquipmentCmdEnum;
import com.hitqz.robot.camera.dto.*;
import com.hitqz.robot.common.core.util.R;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.Objects;

/**
 * @author wengyx
 * @date 2024/8/7
 */
@Service
@AllArgsConstructor
@Slf4j
public class PatrolCheckTypeServiceIml extends ServiceImpl<PatrolCheckTypeMapper, PatrolCheckType> implements PatrolCheckTypeService {


    private final ServerProperties serverProperties;
    private final RobotService robotService;
    private final FileProperties fileProperties;
    private final RobotEquipmentService robotEquipmentService;
    private final EquipmentFactory equipmentFactory;

    @Override
    public R detectByFile(Integer checkTypeId, String localPath) {
        try {
            if (StrUtil.isBlank(localPath)){
                return R.failed("未找到文件");
            }
            PatrolCheckType checkType = this.getById(checkTypeId);
            if (!Objects.equals(checkType.getIsVision(),1)){
                return R.failed("仅视觉检测项支持上传文件测试");
            }
            String visionUrl = checkType.getVisionUrl();
            if (StrUtil.isBlank(visionUrl) ){
                return R.failed("视觉检测地址未填写");
            }
            String visionType = checkType.getVisionType();
            if (StrUtil.isBlank(visionType) ){
                return R.failed("视觉类型值未填写");
            }
            Robot robot = robotService.getDefaultRobot();
            String externalIp = StrUtil.isBlank(robot.getExternalIp()) ? "127.0.0.1" : robot.getExternalIp();
            String externalHost = StrUtil.isBlank(robot.getExternalPort()) ? externalIp + ":" + serverProperties.getPort() : externalIp + ":" + robot.getExternalPort();
            String host = (visionUrl.contains("127.0.0.1") || visionUrl.contains("localhost")) ? "127.0.0.1:"+ serverProperties.getPort() : externalHost;
            String basePath = fileProperties.getLocal().getBasePath().replace("\\\\", "/").replace("\\","/");
            log.info("----{}",basePath);
            localPath = localPath.replace("\\\\", "/").replace("\\","/");
            log.info("----{}",localPath);
            String uri = localPath.replace(basePath, "");
            String url = "http://"+ host + "/file/" + uri;
            log.info("-----{}",url);
            HashMap<String, Object> query = new HashMap<>();
            query.put("url",url);
            query.put("rectype",Integer.parseInt(visionType));
            log.info("视觉地址：{},参数:{}",visionUrl, JSONObject.toJSONString(query));
            String result = HttpUtil.post(visionUrl, JSONObject.toJSONString(query), 2500);
            log.info("视觉检测结果: {}", result);
            //删除缓存
            if (FileUtil.exist(localPath)){
                FileUtil.del(localPath);
            }
            return R.ok(result);
        }catch (Exception e){
            return R.failed("调用检测失败:"+e.getMessage());
        }
    }

    @Override
    public R detectByEquipment(Integer checkTypeId, Integer equipmentId) {
        try{
            PatrolCheckType checkType = this.getById(checkTypeId);
            RobotEquipment equipment = robotEquipmentService.getById(equipmentId);
            IEquipmentService service = equipmentFactory.getServiceByBrand(equipment.getBrand());
            if (service==null){
                return R.failed("所选外设品牌暂不支持检测");
            }
            String mediaType = checkType.getMediaType();
            String localPath = "";
            QueryParamsDto queryParamsDto = new QueryParamsDto();
            queryParamsDto.setPassword(equipment.getPassword());
            queryParamsDto.setUsername(equipment.getUsername());
            queryParamsDto.setPort(equipment.getPort());
            queryParamsDto.setChannel(equipment.getChannel());
            queryParamsDto.setIp(equipment.getIp());
            TakePicParamsDto paramsDto = new TakePicParamsDto();
            paramsDto.setBasePath(fileProperties.getLocal().getBasePath());
            paramsDto.setFolder(File.separator + "temp" + File.separator + DateUtil.format(new Date(), "yyyyMMdd") + File.separator);
            if (Objects.equals(mediaType, MediaEnum.PICTURE.getType())){
                //localPath = service.takePic(equipment.getIp(), equipment.getChannel(), fileProperties.getLocal().getBasePath(), "temp").getAbsolutePath();
                MediaFileDto mediaFileDto = (MediaFileDto) service.executeCmd(queryParamsDto, true, EquipmentCmdEnum.TAKE_PIC,paramsDto);
                localPath = mediaFileDto.getAbsolutePath();
                return this.detectByFile(checkTypeId, localPath);
            }
            if (Objects.equals(mediaType, MediaEnum.VIDEO.getType())){
                service.executeCmd(queryParamsDto, true, EquipmentCmdEnum.START_RECORD,paramsDto);
                Thread.sleep(4000);//延时4秒，实际视频可能才3秒多点
                MediaFileDto mediaFileDto = (MediaFileDto) service.executeCmd(queryParamsDto, true, EquipmentCmdEnum.STOP_RECORD,paramsDto);
                localPath = mediaFileDto.getAbsolutePath();
                return this.detectByFile(checkTypeId, localPath);
            }
            if (Objects.equals(mediaType, MediaEnum.THERMOMETRY.getType())){
                MediaFileDto mediaFileDto = (MediaFileDto) service.executeCmd(queryParamsDto, true, EquipmentCmdEnum.TAKE_PIC,paramsDto);
                String url = "http://127.0.0.1:"+serverProperties.getPort()+"/"+mediaFileDto.getRelativePath();
                //MediaFileDto mediaFileDto = service.takePic(equipment.getIp(), equipment.getChannel(), fileProperties.getLocal().getBasePath(), "temp");
                //String url = "http://127.0.0.1:"+serverProperties.getPort()+"/"+mediaFileDto.getRelativePath();
                InitRegionMeasureDTO dto = new InitRegionMeasureDTO();
                dto.setIp(equipment.getIp());
                dto.setTemplateAreas(Lists.newArrayList());
                dto.setRuleIdList(Lists.newArrayList());
                //List<Integer> integers = service.initRegionAndStartMonitor(dto);
                MeasureTemplateDto ruleDto = (MeasureTemplateDto) service.executeCmd(
                        queryParamsDto, true, EquipmentCmdEnum.INIT_REGION_AND_START_MONITOR, dto
                );
                dto.setRuleIdList(ruleDto.getConfig());
                Thread.sleep(2000);
                //AreaTemplateDTO areaTemplateDTO = service.stopRegionMonitor(dto);
                AreaTemplateDTO areaTemplateDTO = (AreaTemplateDTO) service.executeCmd(queryParamsDto, true,
                        EquipmentCmdEnum.STOP_MONITOR, dto);
                HashMap<String, String> map = new HashMap<>();
                map.put("temperature",areaTemplateDTO.getMaxTemplate()+"℃");
                map.put("url",url);
                return R.ok(JSONObject.toJSONString(map));
            }
            if (Objects.equals(mediaType, MediaEnum.AUDIO.getType())){
                service.executeCmd(queryParamsDto, true, EquipmentCmdEnum.START_RECORD,paramsDto);
                Thread.sleep(3000);
                MediaFileDto mediaFileDto = (MediaFileDto) service.executeCmd(queryParamsDto, true, EquipmentCmdEnum.STOP_RECORD,paramsDto);
                mediaFileDto = transferMp4toWav(mediaFileDto);
                localPath = mediaFileDto.getAbsolutePath();
                return this.detectByFile(checkTypeId, localPath);
            }
            return R.ok();
        }catch (Exception e){
            return R.failed("调用外设检测失败"+e.getMessage());
        }
    }


    private MediaFileDto transferMp4toWav(MediaFileDto mediaFileDto){
        String mp4Path = mediaFileDto.getAbsolutePath();
        String mp4Name = mediaFileDto.getName();
        String mp4RelativePath = mediaFileDto.getRelativePath();
        String wavName = mp4Name.replace(".mp4", ".wav");
        String wavFilePath = mp4Path.replace(mp4Name, wavName);
        String wavRelativePath = mp4RelativePath.replace(mp4Name, wavName);
        // 构建 ffmpeg 命令：从 MP4 提取音频并保存为 WAV
        String command = "ffmpeg -i " + mp4Path + " -vn -acodec pcm_s16le -ar 44100 -ac 2 " + wavFilePath;
        try {
            ProcessBuilder processBuilder = new ProcessBuilder(command.split(" "));
            processBuilder.redirectErrorStream(true); // 合并标准错误和标准输出流
            Process process = processBuilder.start();
            int exitCode = process.waitFor();
            log.info("[HK]音频提取结束:{},{}",wavFilePath, exitCode);
        }catch (Exception e){
            log.error("[HK]音频提取失败",e);
        }

        File wavFile = new File(wavFilePath);
        if (wavFile.exists()) {
            log.info("[HK]生成 WAV 文件成功: {}", wavFilePath);
            // 可选：删除原始 MP4 文件
            log.info("[HK]删除原文件,{}", new File(mp4Path).delete());
        }
        MediaFileDto wavFileDto = new MediaFileDto();
        wavFileDto.setAbsolutePath(wavFilePath);
        wavFileDto.setName(mp4Name);
        wavFileDto.setRelativePath(wavRelativePath);
        return wavFileDto;
    }


}
